from gm.api import *
import datetime
import numpy as np
import pandas as pd
import statsmodels.api as sm
from MSCI_tools import msci_tools
set_token("a71a8083b68e73817e93f7f196b030482abe5939")
day_time,hour_and_mins=str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')).split(" ")

"""
低波策略又名防守策略，有两种计算方法，低beta 或者 低波动。
低波动用日收益率的标准差（不是股价的标准差）。
这样可以排除股价高低的影响。
https://www.joinquant.com/post/7200?tag=algorithm
"""


#这里使用的是使用股票收盘价与同期指数的绝对值进行回归
def get_beta_weight_1_not_support(symbol,now,count,market_index = "SHSE.000001"):
    """
    一般用单个股票资产的历史收益率对同期指数（大盘）收益率进行回归，回归系数就是Beta系数。
    """
    last_day = get_previous_trading_date("SHSE",now)
    market_data = history_n(symbol=market_index, frequency="1d", count=count,
                     end_time=last_day,
                     fields="high,low,close",
                     fill_missing="last")

    market_close = msci_tools.get_data_value(market_data,"close")

    symbol_data = history_n(symbol=symbol, frequency="1d", count=count,
                     end_time=last_day,
                     fields="high,low,close",
                     fill_missing="last")

    symbol_close = msci_tools.get_data_value(symbol_data,"close")

    market_close = sm.add_constant(market_close)
    model_ = sm.OLS(symbol_close, market_close)
    results_ = model_.fit()
    weight_ = (results_.params[1])
    return weight_

#这里使用的是收益进行计算
def get_beta_weight_2(symbol,now,count,market_index = "SHSE.000001"):
    """
    一般用单个股票资产的历史收益率对同期指数（大盘）收益率进行回归，回归系数就是Beta系数。
    """
    last_day = get_previous_trading_date("SHSE",now)
    market_data = history_n(symbol=market_index, frequency="1d", count=count,
                     end_time=last_day,
                     fields="high,low,close",
                     fill_missing="last")

    market_close = msci_tools.get_data_value(market_data,"close")

    market_close_ratio = []
    for i in range(1,len(market_close)):
        ratio = (market_close[i] - market_close[i-1])/market_close[i-1]
        ratio = (0.99 ** (len(market_close) - i)) * ratio
        market_close_ratio.append(ratio)



    symbol_data = history_n(symbol=symbol, frequency="1d", count=count,
                     end_time=last_day,
                     fields="high,low,close",
                     fill_missing="last")

    symbol_close = msci_tools.get_data_value(symbol_data,"close")

    symbol_close_ratio = []
    for i in range(1,len(symbol_close)):
        ratio = (symbol_close[i] - symbol_close[i-1])/symbol_close[i-1]
        ratio = (0.99 ** (len(market_close) - i)) * ratio
        symbol_close_ratio.append(ratio)

        market_close_ratio = sm.add_constant(market_close_ratio)
    model_ = sm.OLS(symbol_close_ratio, market_close_ratio)
    results_ = model_.fit()
    weight_ = (results_.params[1])
    return weight_





#一种波动率的方法，采用wind波动率计算法,不建议使用
def get_volatility_wind(symbol,now,count):

    """
    波动率来源：https://www.joinquant.com/post/10884?tag=algorithm
    貌似wind的公式
    :param symbol:
    :param now:
    :return:
    """
    last_day = get_previous_trading_date("SHSE",now)
    data = history_n(symbol=symbol, frequency="1d", count=count,
                         end_time=last_day,fields="high,low,close",fill_missing="last")

    close = msci_tools.get_data_value(data,"close")

    close = pd.DataFrame(close)
    stocks_change = close.apply(lambda x: np.log(x) - np.log(x.shift(1)))
    # 计算30,60,90日波动率,年化之
    daily_vol = stocks_change.std()
    annual_vol = daily_vol * 252 ** 0.5
    return annual_vol.values[0]

#波动率的简单方法,感觉比wind的要好
def get_volatility_normal(symbol,now,count):

    last_day = get_previous_trading_date("SHSE",now)
    data = history_n(symbol=symbol, frequency="1d", count=count,
                         end_time=last_day,fields="high,low,close",fill_missing="last")
    close = msci_tools.get_data_value(data,"close")

    res = np.var(close)/np.mean(close)
    res = np.sqrt(res)
    return res

if __name__ == "__main__":
    pass
